#!/usr/bin/env bash
#
# Startup script for query under *nix systems (it works under NT/cygwin too).

echo "$0 $PWD"

usage()
{
    echo "Usage: ${0##*/} [-d] {start|stop|run|restart|check|supervise} [ CONFIGS ... ] "
    exit 1
}

[ $# -gt 0 ] || usage


##################################################
# Some utility functions
##################################################
findDirectory()
{
  local L OP=$1
  shift
  for L in "$@"; do
    [ "$OP" "$L" ] || continue
    printf %s "$L"
    break
  done
}

running()
{
  local PID=$(cat "$1" 2>/dev/null) || return 1
  kill -0 "$PID" 2>/dev/null
}

started()
{
  # wait for 60s to see "STARTED" in PID file, needs query-started.xml as argument
  for T in 1 2 3 4 5 6 7 9 10 11 12 13 14 15
  do
    sleep 4
    [ -z "$(grep STARTED $1 2>/dev/null)" ] || return 0
    [ -z "$(grep STOPPED $1 2>/dev/null)" ] || return 1
    [ -z "$(grep FAILED $1 2>/dev/null)" ] || return 1
    local PID=$(cat "$2" 2>/dev/null) || return 1
    kill -0 "$PID" 2>/dev/null || return 1
    echo -n ". "
  done

  return 1;
}


readConfig()
{
  (( DEBUG )) && echo "Reading $1.."
  source "$1"
}



##################################################
# Get the action & configs
##################################################
CONFIGS=()
NO_START=0
DEBUG=0

while [[ $1 = -* ]]; do
  case $1 in
    -d) DEBUG=1 ;;
  esac
  shift
done
ACTION=$1
shift

##################################################
# Set tmp if not already set.
##################################################
TMPDIR=${TMPDIR:-/tmp}

##################################################
# Query's hallmark
##################################################
QUERY_INSTALL_TRACE_FILE="etc/query.xml"

##################################################
# Set QUERY_HOME
##################################################
BASEDIR=$(dirname $0)
QUERY_HOME=$BASEDIR

##################################################
# Try to determine QUERY_HOME if not set
##################################################
if [ -z "$QUERY_HOME" ]
then
  QUERY_SH=$0
  case "$QUERY_SH" in
    /*)     QUERY_HOME=${QUERY_SH%/*/*} ;;
    ./*/*)  QUERY_HOME=${QUERY_SH%/*/*} ;;
    ./*)    QUERY_HOME=.. ;;
    */*/*)  QUERY_HOME=./${QUERY_SH%/*/*} ;;
    */*)    QUERY_HOME=. ;;
    *)      QUERY_HOME=.. ;;
  esac

  if [ ! -f "$QUERY_HOME/$QUERY_INSTALL_TRACE_FILE" ]
  then
    QUERY_HOME=
  fi
fi


##################################################
# if no QUERY_HOME, search likely locations.
##################################################
if [ -z "$QUERY_HOME" ] ; then
  STANDARD_LOCATIONS=(
        "/usr/share"
        "/usr/share/java"
        "${HOME}"
        "${HOME}/src"
        "${HOME}/opt"
        "/opt"
        "/java"
        "/usr/local"
        "/usr/local/share"
        "/usr/local/share/java"
        "/home"
        )
  QUERY_DIR_NAMES=(
        "query"
        )

  for L in "${STANDARD_LOCATIONS[@]}"
  do
    for N in "${QUERY_DIR_NAMES[@]}"
    do
      POSSIBLE_QUERY_HOME=("$L/"$N)
      if [ ! -d "$POSSIBLE_QUERY_HOME" ]
      then
        # Not a directory. skip.
        unset POSSIBLE_QUERY_HOME
      elif [ ! -f "$POSSIBLE_QUERY_HOME/$QUERY_INSTALL_TRACE_FILE" ]
      then
        # Trace file not found. skip.
        unset POSSIBLE_QUERY_HOME
      else
        # Good hit, Use it
        QUERY_HOME=$POSSIBLE_QUERY_HOME
        # Break out of QUERY_DIR_NAMES loop
        break
      fi
    done
    if [ -n "$POSSIBLE_QUERY_HOME" ]
    then
      # We have found our QUERY_HOME
      # Break out of STANDARD_LOCATIONS loop
      break
    fi
  done
fi


##################################################
# No QUERY_HOME yet? We're out of luck!
##################################################
if [ -z "$QUERY_HOME" ]; then
  echo "** ERROR: QUERY_HOME not set, you need to set it or install in a standard location"
  exit 1
fi

cd "$QUERY_HOME"
QUERY_HOME=$PWD

#####################################################
# Find a location for the pid file
#####################################################
if [ -z "$QUERY_RUN" ]
then
  QUERY_RUN=$(findDirectory -w /var/run /usr/var/run $QUERY_HOME /tmp)
fi

#####################################################
# Find a pid and state file
#####################################################
if [ -z "$QUERY_PID" ]
then
  QUERY_PID="$QUERY_RUN/query.pid"
fi

if [ -z "$QUERY_STATE" ]
then
  QUERY_STATE=$QUERY_HOME/query.state
fi
JAVA_OPTIONS+=("-Dquery.state=$QUERY_STATE")
rm -f $QUERY_STATE

##################################################
# Setup JAVA if unset
##################################################
if [ -z "$JAVA" ]
then
  JAVA=$(which java)
fi

if [ -z "$JAVA" ]
then
  echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2
  exit 1
fi

#####################################################
# This is how the Query server will be started
#####################################################

QUERY_JAR=$QUERY_HOME/query.jar

QUERY_YML_FILE=$QUERY_HOME/queryBootstrapper-daemon.yml

RUN_ARGS=(-jar "$QUERY_JAR" server "$QUERY_YML_FILE")
RUN_CMD=("$JAVA" ${RUN_ARGS[@]})

##################################################
# Do the action
##################################################
case "$ACTION" in
  start)
    echo -n "Starting Query: "

    if (( NO_START )); then
      echo "Not starting Query - NO_START=1";
      exit
    fi

    if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1
    then
      unset CH_USER
      if [ -n "$QUERY_USER" ]
      then
        CH_USER="-c$QUERY_USER"
      fi

      start-stop-daemon -S -p"$QUERY_PID" $CH_USER -d"$QUERY_HOME" -b -m -a "$JAVA" -- "${RUN_ARGS[@]}" --daemon

    else

      if [ -f "$QUERY_PID" ]
      then
        if running $QUERY_PID
        then
          echo "Already Running!"
          exit 1
        else
          # dead pid file - remove
          rm -f "$QUERY_PID"
        fi
      fi

      if [ "$QUERY_USER" ]
      then
        touch "$QUERY_PID"
        chown "$QUERY_USER" "$QUERY_PID"
        # Broken solution: wordsplitting, pathname expansion, arbitrary command execution, etc.
        su - "$QUERY_USER" -c "
          echo "Number 1"
          exec ${RUN_CMD[*]} --daemon &
          disown \$!
          echo \$! > '$QUERY_PID'"
      else
        echo "Number 2"
        "${RUN_CMD[@]}" &
        disown $!
        echo $! > "$QUERY_PID"
      fi

    fi

    if expr "${CONFIGS[*]}" : '.*etc/querry-started.xml.*' >/dev/null
    then
      if started "$QUERY_STATE" "$QUERY_PID"
      then
        echo "OK `date`"
      else
        echo "FAILED `date`"
      fi
    else
      echo "ok `date`"
    fi

    ;;

  stop)
    echo -n "Stopping Query: "
    if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1; then
      start-stop-daemon -K -p"$QUERY_PID" -d"$QUERY_HOME" -a "$JAVA" -s HUP

      TIMEOUT=30
      while running "$QUERY_PID"; do
        if (( TIMEOUT-- == 0 )); then
          start-stop-daemon -K -p"$QUERY_PID" -d"$QUERY_HOME" -a "$JAVA" -s KILL
        fi

        sleep 1
      done

      rm -f "$QUERY_PID"
      echo OK
    else
      PID=$(cat "$QUERY_PID" 2>/dev/null)
      kill "$PID" 2>/dev/null

      TIMEOUT=30
      while running $QUERY_PID; do
        if (( TIMEOUT-- == 0 )); then
          kill -KILL "$PID" 2>/dev/null
        fi

        sleep 1
      done

      rm -f "$QUERY_PID"
      echo OK
    fi

    ;;

  restart)
    QUERY_SH=$0
    if [ ! -f $QUERY_SH ]; then
      if [ ! -f $QUERY_HOME/query.sh ]; then
        echo "$QUERY_HOME/query.sh does not exist."
        exit 1
      fi
      QUERY_SH=$QUERY_HOME/query.sh
    fi

    "$QUERY_SH" stop "$@"
    "$QUERY_SH" start "$@"

    ;;

  supervise)
    #
    # Under control of daemontools supervise monitor which
    # handles restarts and shutdowns via the svc program.
    #
    echo "Number 3"
    exec "${RUN_CMD[@]}"

    ;;

  run|demo)
    echo "Running Query: "

    if [ -f "$QUERY_PID" ]
    then
      if running "$QUERY_PID"
      then
        echo "Already Running!"
        exit 1
      else
        # dead pid file - remove
        rm -f "$QUERY_PID"
      fi
    fi

    echo "Number 4"
    exec "${RUN_CMD[@]}"
    ;;

  check|status)
    echo "Checking arguments to Query: "
    echo "QUERY_HOME     =  $QUERY_HOME"
    echo "QUERY_PID      =  $QUERY_PID"
    echo "JAVA           =  $JAVA"
    echo "RUN_CMD        =  ${RUN_CMD[*]}"
    echo

    if [ -f "$QUERY_PID" ]
    then
      echo "QUERY running pid=$(< "$QUERY_PID")"
      exit 0
    fi
    exit 1

    ;;

  *)
    usage

    ;;
esac

exit 0
